package com.zut.subject.domain.service.impl;

import com.alibaba.fastjson.JSON;
import com.zut.subject.common.enums.IsDeletedFlagEnum;
import com.zut.subject.domain.config.ThreadPoolConfig;
import com.zut.subject.domain.convert.ConvertCategory;
import com.zut.subject.domain.convert.ConvertLabel;
import com.zut.subject.domain.entity.SubjectCategoryBo;
import com.zut.subject.domain.entity.SubjectLabelBo;
import com.zut.subject.domain.service.SubjectCategoryDomainService;
import com.zut.subject.infra.basic.entity.SubjectCategory;
import com.zut.subject.infra.basic.entity.SubjectLabel;
import com.zut.subject.infra.basic.entity.SubjectMapping;
import com.zut.subject.infra.basic.service.SubjectCategoryService;
import com.zut.subject.infra.basic.service.SubjectLabelService;
import com.zut.subject.infra.basic.service.SubjectMappingService;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.util.*;
import java.util.concurrent.FutureTask;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.stream.Collectors;

@Slf4j
@Service
public class SubjectCategoryDomainServiceImpl implements SubjectCategoryDomainService {


    @Resource
    private SubjectCategoryService subjectCategoryService;

    @Resource
    private SubjectMappingService subjectMappingService;

    @Resource
    private SubjectLabelService subjectLabelService;

    @Resource
    private ThreadPoolExecutor labelThreadPool;

    public void add(SubjectCategoryBo subjectCategoryBo) {
        if(log.isInfoEnabled()){
            log.info("subjectCategoryDomainService.add.Bo:{}", JSON.toJSONString(subjectCategoryBo));
        }
        subjectCategoryService.insert(ConvertCategory.INSTANCE.toSubjectCategory(subjectCategoryBo));

    }


    public List<SubjectCategoryBo> queryPrimaryCategory(SubjectCategoryBo subjectCategoryBo) {
        try {

            //将controller层传入的bo转化为subjectCategory类型
            SubjectCategory subjectCategory = ConvertCategory.INSTANCE.toSubjectCategory(subjectCategoryBo);
            //设置isDelete值为0，选择逻辑上未被删除的数据
            subjectCategory.setIsDelete(IsDeletedFlagEnum.UN_DELETED.getCode());
            //将subjectCategory传到infra层，将返回的List<SubjectCategory>转化为List<SubjectCategoryBo>
            List<SubjectCategory> List= subjectCategoryService.queryPrimaryCategory(subjectCategory);
            List<SubjectCategoryBo> boList = ConvertCategory.INSTANCE.toSubjectCategory(List);

            //将boList返回到controller层
            if (log.isInfoEnabled()){
                log.info("subjectCategoryDomainService传出的数据为:{}", JSON.toJSONString(boList));
            }

            boList.forEach(bo->{
                Integer count= subjectCategoryService.queryCount(bo.getId());
                bo.setCount(count);
            });
            return boList;
        } catch (Exception exception) {
            if (log.isInfoEnabled()){
                log.error("subjectCategoryDomainService发生错误！");
            }
            return null;
        }
    }

    public boolean update(SubjectCategoryBo subjectCategoryBo) {
        SubjectCategory subjectCategory = ConvertCategory.INSTANCE.toSubjectCategory(subjectCategoryBo);

        if (log.isInfoEnabled()){
            log.info("domain层向infra层传输数据为：{}",subjectCategory);
        }
        int update = subjectCategoryService.update(subjectCategory);
        return update>0;

    }

    public boolean delete(SubjectCategoryBo subjectCategoryBo) {

        SubjectCategory subjectCategory = ConvertCategory.INSTANCE.toSubjectCategory(subjectCategoryBo);

        //设置isDelete为1，代表数据已经被删除
        subjectCategory.setIsDelete(IsDeletedFlagEnum.DELETED.getCode());
        if (log.isInfoEnabled()){
            log.info("domain层向infra层传输数据为：{}",subjectCategory);
        }
        int update = subjectCategoryService.update(subjectCategory);
        //数据大于0返回true
        return update>0;

    }

    @SneakyThrows
    @Override
    public List<SubjectCategoryBo> queryCategoryAndLabel(SubjectCategoryBo subjectCategoryBo) {
        SubjectCategoryBo subjectCategoryBo1=new SubjectCategoryBo();
        //将大类id取出来作为父类id
        subjectCategoryBo1.setParentId(subjectCategoryBo.getId());
        subjectCategoryBo1.setIsDelete(IsDeletedFlagEnum.UN_DELETED.getCode());
        SubjectCategory subjectCategory = ConvertCategory.INSTANCE.toSubjectCategory(subjectCategoryBo1);
        List<SubjectCategory> list = subjectCategoryService.queryPrimaryCategory(subjectCategory);
        List<SubjectCategoryBo> boList = ConvertCategory.INSTANCE.toSubjectCategory(list);


        List<FutureTask<Map<Integer,List<SubjectLabelBo>>>> labelList = new LinkedList<>();
        Map<Integer, List<SubjectLabelBo>> maps=new HashMap<>();

        boList.forEach(bo->{
            FutureTask<Map<Integer,List<SubjectLabelBo>>> task=new FutureTask<>(()->
                    getLabelBoList(bo));
            //把任务执行完成的结果放到list集合中
            labelList.add(task);
            //提交任务给线程池执行
            labelThreadPool.submit(task);
        });
        //取出执行线程池执行完成后的结果
        for (FutureTask<Map<Integer, List<SubjectLabelBo>>> task : labelList) {
            Map<Integer, List<SubjectLabelBo>> map = task.get();
            if (CollectionUtils.isEmpty(map)){
                continue;
            }
            maps.putAll(map);
        }
        //将全部的结果放到boList中去
        boList.forEach(bo->{
            bo.setLabelBoList(maps.get(bo.getId()));
        });

        return boList;
    }

    private Map<Integer,List<SubjectLabelBo>> getLabelBoList(SubjectCategoryBo bo) {
        Map<Integer,List<SubjectLabelBo>> map=new HashMap<>();
        List<SubjectMapping> mappings = subjectMappingService.queryLabelIdByCategoryId(bo.getId());
        //将map表中labelId提取出来做成一个集合
        List<Integer> collect = mappings.stream().map(SubjectMapping::getLabelId).collect(Collectors.toList());
        List<SubjectLabel> subjectLabels = subjectLabelService.queryById(collect);
        map.put(bo.getId(),ConvertLabel.INSTANCE.toListSubjectLabelBo(subjectLabels));
        return map;
    }
}
